<?php

namespace System\Core;

if (!defined('BASEPATH')) die('Access Denied.');

/**
 * µMVC Framework (c) 2011.
 * 
 * PHP5 MVC Framework software for PHP 5.2.17 or later
 * 
 * @package         µMVC
 * @filename        system/core/input.class.php
 * @copyright       Lanz (c) 2011.
 * 
 */
class InputException extends CommonException
{
    
}

;

/**
 * Input class
 * Handles access to POST, uri params and cookie variables and similar user based
 * input values.
 * 
 * @package         µMVC
 * @subpackage      Core
 * @category        System
 * 
 */
class Input extends BaseSingleton
{

    /**
     * URI instance.
     * 
     * @var type object
     */
    private $_uri;

    /**
     * URI arguments.
     * 
     * @var array
     */
    private $_args = array();

    function __construct()
    {
        $this->_uri = URI::instance();
        $this->_setArgs();
        Log::instance()->write(Log::DEBUG, 'Input Class intitialized');
    }

    /**
     * Sets up the URI arguments in an assosiative array for easier handling
     * in the application.
     */
    private function _setArgs()
    {
        // Sort out the arguments supplied with the URI string and re-index
        // the array to start from 1 instead of 0.
        $args = $this->_uri->getSegments();
        if (count($args) > 2)
        {
            unset($args[1], $args[2]);
            $args = array_values($args);
        }
        else
        {
            $args = array();
        }

        // If we have an even number of key/values then convert it into an
        // assosiative array. It's either or in this case, you can not have
        // both key/value pairs and individual values in the same URI.
        // if the dev want it that way then he need to use the uri segment
        // and handle the data himself.
        if (count($args) % 2 == 0)
        {
            for ($i = 0; $i < count($args) - 1; $i += 2)
            {
                $this->_args[$args[$i]] = $args[$i + 1];
            }
        }
    }

    /**
     * Returns one a value from the URI arguments. Usually we would have
     * called this function getParam() but shortened if for easier typing in
     * the app.
     * 
     * @param string $key
     * @return string 
     */
    public function param($key, $return = FALSE)
    {
        if (isset($this->_args[$key]))
        {
            return $this->_args[$key];
        }

        return $return;
    }

    /**
     * Returns the whole array from the URI arguments. Usually we would have
     * called this function getParams() but shortened if for easier typing in
     * the app.
     * 
     * @return array
     */
    public function params()
    {
        return $this->_args;
    }

    public function isPost()
    {
        return count($_POST) > 0;
    }

    public function post($key, $return = FALSE)
    {
        if (isset($_POST[$key]))
        {
            return $_POST[$key];
        }

        return $return;
    }

    public function posts()
    {
        return $_POST;
    }

    public function ipLongAddr()
    {
        // Returns a correctly formated unsigned int.
        return sprintf("%u", ip2long($this->getIpAddr()));
    }

    public function getIpAddr()
    {
        // This code is easily fooled by proxies but at least slightly
        // better than just using REMOTE_ADDR.
        if (!empty($_SERVER['HTTP_CLIENT_IP']))
        {
            $ip = $_SERVER['HTTP_CLIENT_IP']; // share internet
        }
        elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
        {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; // pass from proxy
        }
        else
        {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        return $ip;
    }

    /**
     * Use this function to retrive a cookie instead of directly accessing the
     * $_COOKIE variable. 
     * 
     * @param string $key name of the cookie.
     * @return mixed returns FALSE if the cookie is not available.
     */
    function getCookie($key, $return = FALSE)
    {
        $config = \System\Core\Config::instance();
        
        $prefix = $config->getItem('cookie_prefix');
        if (isset($_COOKIE[$prefix.$key]) && !empty($_COOKIE[$prefix.$key]))
        {
            return urldecode($_COOKIE[$config->getItem('cookie_prefix') . $key]);
        }
        else
        {
            return $return;
        }
    }
    
    /**
     * Use this function instead of directly accessing the setcookie function.
     * 
     * @param string $key Name of the cookie.
     * @param mixed $value the value of the cookie.
     * @param type $expiresIn the expiration time in days.
     * @param boolean $sticky if sticky then the expiration time is one year.
     * @param boolean $delete deletes the cookie.
     */
    function setCookie($key, $value, $expiresIn = 0, $sticky = TRUE, $delete = FALSE)
    {
        if ($sticky)
        {
            $expiresIn = time() + ONE_YEAR;
        }
        elseif ($expiresIn > 0)
        {
            $expiresIn = time() + $expiresIn * ONE_DAY;
        }
        elseif ($delete)
        {
            $expiresIn = time() - ONE_HOUR;
        }
        else
        {
            $expiresIn = time() + ONE_DAY;
        }
        
        $config = \System\Core\Config::instance();
        
        @setcookie(
            $config->getItem('cookie_prefix').$key, 
            $value,
            $expiresIn,
            $config->getItem('cookie_path'),
            $config->getItem('cookie_domain'),
            FALSE,
            TRUE
        );
    }   
    
    function deleteCookie($key)
    {
        $this->setCookie($key, '', 0, FALSE, TRUE);
    }
    
}

?>
